package service

import (
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"
	"os"
	"oss-api/library/response"
	"strings"
)

type OssClaims struct {
	username string
	password string
	jwt.StandardClaims
}

// CorsMiddle 跨域配置
func CorsMiddle() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method
		origin := c.Request.Header.Get("Origin")
		c.Header("Access-Control-Allow-Origin", origin)
		c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id")
		c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT")
		c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
		c.Header("Access-Control-Allow-Credentials", "true")

		// 放行所有OPTIONS方法
		if method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
		}
		// 处理请求
		c.Next()
	}
}

// CheckConfig 检查配置信息是否存在
func CheckConfig() gin.HandlerFunc {
	return func(c *gin.Context) {
		if _, err := os.Stat("config/config-test.yaml"); err != nil {
			if os.IsExist(err) {
				c.JSON(http.StatusBadRequest, response.Fail("缺失系统配置信息"))
				c.Abort()
				return
			}
		}
		c.Next()
	}
}

// JwtMiddle jwt权限鉴定
func JwtMiddle() gin.HandlerFunc {

	return func(c *gin.Context) {
		token := c.Request.Header.Get("Authorization")
		// 先判空
		if token == "" {
			c.JSON(http.StatusUnauthorized, response.Fail("请求头中auth为空"))
			c.Abort()
			return
		}
		// 判断token的前缀是否正确
		items := strings.SplitN(token, " ", 2)
		if !(len(items) == 2 && items[0] == "Oss") {
			c.JSON(http.StatusNonAuthoritativeInfo, response.Fail("请求头中auth格式有误"))
			c.Abort()
			return
		}

		claims, err := jwt.ParseWithClaims(items[1], &OssClaims{}, func(token *jwt.Token) (interface{}, error) {
			return []byte("oss-cloud"), nil
		})

		if err != nil {
			c.JSON(http.StatusUnauthorized, response.Fail("解析Token失败"))
			c.Abort()
			return
		}
		// 验证是否失效
		if !claims.Valid {
			c.JSON(http.StatusUnauthorized, response.Fail("无效的Token"))
			c.Abort()
			return
		}
		c.Next()
	}
}
